﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace AutoUpdaterDotNET
{
    public class INIFile
    {
        private string path;

        private static INIFile _iniFile;

        /// <summary>
        /// 获取INIHelp实例
        /// </summary>
        public static INIFile Instance
        {
            get
            {
                if (_iniFile == null)
                {
                    _iniFile = new INIFile();
                }
                return _iniFile;
            }
        }

        private INIFile()
        {
            //this.path = System.Environment.CurrentDirectory + "\\setup.ini";
            string baseDire = AppDomain.CurrentDomain.BaseDirectory;
            string deadStr = baseDire + "config.ini";
            this.path = deadStr;
        }

        public INIFile(string path)
        {
            this.path = path;

        }
        public string Path
        {
            get { return path; }
            set { path = value; }
        }
        /// <summary>
        /// 写INI文件
        /// </summary>
        /// <param name="section">段落</param>
        /// <param name="key">键</param>
        /// <param name="iValue">值</param>
        public void IniWriteValue(string section, string key, string iValue)
        {
            WritePrivateProfileString(section, key, iValue, this.Path);
        }

        /// <summary>
        /// 读取INI文件
        /// </summary>
        /// <param name="section">段落</param>
        /// <param name="key">键</param>
        /// <returns>值</returns>
        public string IniReadValue(string section, string key)
        {
            StringBuilder temp = new StringBuilder(2048);
            int i = GetPrivateProfileString(section, key, "", temp, 2048, this.Path);
            return temp.ToString();
        }


        public string[] GetAllSection()
        {
            int MAX_BUFFER = 32767;
            IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER);
            int bytesReturned = GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, this.path);
            if (bytesReturned == 0)
            {
                Marshal.FreeCoTaskMem(pReturnedString);
                return null;
            }
            string local = Marshal.PtrToStringAnsi(pReturnedString, (int)bytesReturned).ToString();
            Marshal.FreeCoTaskMem(pReturnedString);
            //use of Substring below removes terminating null for split
            return local.Substring(0, local.Length - 1).Split('\0');
        }

        public Dictionary<string, string> GetINISection(String section)
        {
            Dictionary<string, string> dics = new Dictionary<string, string>();
            byte[] buffer = new byte[32768];
            int bufLen = 0;
            bufLen = GetPrivateProfileSection(section, buffer, buffer.GetUpperBound(0), this.path);
            if (bufLen > 0)
            {
                StringBuilder sb = new StringBuilder();
                int flag = -1;
                int beginindex = 0;
                for (int i = 0; i < bufLen; i++)
                {
                    if (buffer[i] == 0)
                    {
                        if (buffer[i - 1] != 0)
                        {
                            flag = 0;
                        }
                    }
                    if (flag == 0)
                    {
                        sb.Append(System.Text.Encoding.Default.GetString(buffer, beginindex, i - beginindex));
                        beginindex = i + 1;
                        string[] arr = sb.ToString().Split('=');
                        if (!dics.ContainsKey(arr[0]))
                            dics.Add(arr[0], arr[1]);

                        sb = new StringBuilder();
                        flag = -1;
                    }
                }
            }
            return dics;
        }

        /// <summary>
        /// INI文件读取读取
        /// </summary>
        /// <param name="section">section：要读取的段落名</param>
        /// <param name="key">key: 要读取的键</param>
        /// <param name="defVal">defVal: 读取异常的情况下的缺省值</param>
        /// <param name="retVal">retVal: key所对应的值，如果该key不存在则返回空值</param>
        /// <param name="size">size: 值允许的大小</param>
        /// <param name="filePath">filePath: INI文件的完整路径和文件名</param>
        /// <returns></returns>
        [DllImport("kernel32.dll")]
        private static extern int GetPrivateProfileString(string section, string key, string defVal, StringBuilder retVal, int size, string filePath);

        /// <summary>
        /// INI文件读取读取
        /// </summary>
        /// <param name="section">section：要读取的段落名</param>
        /// <param name="key">key: 要读取的键</param>
        /// <param name="defVal">defVal: 读取异常的情况下的缺省值</param>
        /// <param name="retVal">retVal: 此参数类型不是string，而是Byte[]用于返回byte类型的section组或键值组。</param>
        /// <param name="size">size: 值允许的大小</param>
        /// <param name="filePath">filePath: INI文件的完整路径和文件名</param>
        /// <returns></returns>
        [DllImport("kernel32.dll")]
        private static extern int GetPrivateProfileString(string section, string key, string defVal, Byte[] retVal, int size, string filePath);

        /// <summary>
        /// ini文件写
        /// </summary>
        /// <param name="section">section: 要写入的段落名</param>
        /// <param name="key">key: 要写入的键，如果该key存在则覆盖写入</param>
        /// <param name="val">val: key所对应的值</param>
        /// <param name="filePath">filePath: INI文件的完整路径和文件名</param>
        /// <returns></returns>
        [DllImport("kernel32.dll")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);

        /// <summary>
        /// INI文件获取所有节点
        /// </summary>
        /// <param name="sections"></param>
        /// <param name="nSize"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll")]
        private static extern int GetPrivateProfileSectionNames(IntPtr sections, int nSize, string filePath);

        /// <summary>
        /// 获取setion下所有的key
        /// </summary>
        /// <param name="lpAppName"></param>
        /// <param name="lpReturnedString"></param>
        /// <param name="nSize"></param>
        /// <param name="lpFileName"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll")]
        protected internal static extern int GetPrivateProfileSection(string lpAppName, byte[] lpReturnedString, int nSize, string lpFileName);
    }
}
